package com.jtpay.sdk.activity;

import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.channel.test.tblPassageTimeStatistics;
import com.jtpay.sdk.R;
import com.jtpay.sdk.adapter.ChannelAdapter;
import com.jtpay.sdk.jtpay.PayUtil;
import com.jtpay.sdk.jtpay.constant.PayConstant;
import com.jtpay.sdk.jtpay.constant.PayExceptionType;
import com.jtpay.sdk.jtpay.listener.PayUtilListener;
import com.jtpay.sdk.jtpay.model.PayChannelInfo;
import com.jtpay.sdk.jtpay.model.PayInfo;
import com.jtpay.sdk.jtpay.utils.PayLogUtil;
import com.jtpay.sdk.model.TimerControlInfo;
import com.jtpay.sdk.util.GlobalUtil;
import com.jtpay.sdk.util.JFTMD5Utils;
import com.jtpay.sdk.util.JftConstants;
import com.jtpay.sdk.util.JftLogUtil;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import de.greenrobot.dao.AbstractDao;
import okhttp3.OkHttpClient;
import okhttp3.ResponseBody;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;

import static com.jtpay.sdk.jtpay.constant.PayExternalConstant.PAY_STATUS;
import static com.jtpay.sdk.jtpay.constant.PayExternalConstant.REQUEST_CODE;
import static com.jtpay.sdk.jtpay.constant.PayExternalConstant.RESULT_CODE;
import static com.jtpay.sdk.jtpay.constant.PayExternalConstant.ZERO_CODE;

public class ChannelActivity extends BaseActivity implements View.OnClickListener, PayUtilListener {
    protected Dialog mProgressDialog;
    private ListView mListView;
    //All list
    private List<PayChannelInfo> mListAll;
    // Sdk list
    private List<PayChannelInfo> mListSDK;
    // browser list
    private List<PayChannelInfo> mListBrowser;
    private PayInfo mPayInfo;
    private PayUtil mPayUtil;
    private Toast mToast;
    private Button mWapBtn;
    private Button mBrowserBtn;
    private Button mSdkBtn;
    private Button mNextBtn;
    private int mChecked = -1;
    private String mTitle;
    private List<PayChannelInfo> mChannelInfoList;
    private long mBeginTime;
    private ChannelAdapter mChannelAdapter;
    private Spinner spinner;
    private TextView mHeadView;
    private String mUserCode;
    private String mComKey;
    private String mPrice;
    private int index = -1; //current passage in arraylist index
    private List<TimerControlInfo> mTimerControlInfos = new ArrayList<>();// timercontrol list
    private List<tblPassageTimeStatistics> mPassageTimeStatisticses = new ArrayList<>();
    private static boolean TimerControl = true; // timer switch
    private Thread mThread;// timer thred

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_channel);
        //database data init
        setupDatabase();
        mToast = Toast.makeText(this, "", Toast.LENGTH_SHORT);
        mPayUtil = GlobalUtil.getInstance().getPayUtil();
        mPayUtil.setActivity(this);
        mPayInfo = mPayUtil.getPayInfo();
        mTitle = getIntent().getStringExtra(JftConstants.JUN_FU_TONG_TITLE) + " " +
                mPayInfo.getPayTypeName();
        mUserCode = getIntent().getStringExtra(JftConstants.JUN_FU_TONG_USER_CODE);
        mComKey = getIntent().getStringExtra(JftConstants.JUN_FU_TONG_COM_KEY);
        mPrice = getIntent().getStringExtra(JftConstants.JUN_FU_TONG_PRICE);
        initData();
        initViews();
        setDoPayListener();
/*
        mThread = new Thread(new ThreadShow());// timer thread
*/
    }

    /*greenDao database operation*/
    private AbstractDao getTblPassageTimeStatisticsDao() {
        return daoSession.getTblPassageTimeStatisticsDao();
    }

    private void insertTblPassageTimeStatistics(tblPassageTimeStatistics passageTimeStatistics) {
        getTblPassageTimeStatisticsDao().insertOrReplace(passageTimeStatistics);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //distory timer
        TimerControl = false;
        mPayUtil.removeTopListener();
    }

    @Override
    protected void onResume() {
        super.onResume();
        //timer start
        /*TimerControl = true;
        if (mThread != null && !mThread.isAlive()) {
            mThread.start();
        }*/
        if (mTimerControlInfos.size() > 0 && index >= 0) {
            mTimerControlInfos.get(index).setStartDate(new Date());
            //拉起支付后才可进行查询支付结果
            mTimerControlInfos.get(index).setDown(false);
        }
    }

    @Override
    protected void onPause() {
        dismiss();
        long endTime = System.currentTimeMillis();
        long time = endTime - mBeginTime;
        PayLogUtil.log("time is " + time);

        super.onPause();
    }

    private void setDoPayListener() {
        mPayUtil.setDoPAYListener(new PayUtil.GetPayPullUpListener() {
            @Override
            public void doPayPullup() {
                if (mTimerControlInfos.size() > 0 && index >= 0) {
                    //pull up time end
                    mTimerControlInfos.get(index).setEndDate(new Date());
                    double timeValue = getCostTime(mTimerControlInfos.get(index).getStartDate(),
                            mTimerControlInfos.get(index).getEndDate());
                    mPassageTimeStatisticses.get(index).setPullupTime(String.valueOf(timeValue));
                    mTimerControlInfos.get(index).DateInfoClear();
                }
            }
        });
    }

    private void initData() {
        getAll();
        getSDk();
        getBrowser();
    }

    private void getAll() {
        mChannelInfoList = mPayInfo.getPayChannelInfo();
        int size = mChannelInfoList.size();
        if (null == mListAll) {
            mListAll = new ArrayList<>(size);
            for (int i = 0; i < size; i++) {
                mListAll.add(mChannelInfoList.get(i));
            }
        }
    }

    private void getSDk() {
        mChannelInfoList = mPayInfo.getPayChannelInfo();
        int size = mChannelInfoList.size();
        if (null == mListSDK) {
            mListSDK = new ArrayList<>(size);
            for (int i = 0; i < size; i++) {
                if (mChannelInfoList.get(i).getTypeCode().equals("SDK")) {
                    mListSDK.add(mChannelInfoList.get(i));
                }
            }
        }
    }

    private void getBrowser() {
        mChannelInfoList = mPayInfo.getPayChannelInfo();
        int size = mChannelInfoList.size();
        if (null == mListBrowser) {
            mListBrowser = new ArrayList<>(size);
            for (int i = 0; i < size; i++) {
                if (!mChannelInfoList.get(i).getTypeCode().equals("SDK")) {
                    mListBrowser.add(mChannelInfoList.get(i));
                }
            }
        }
    }

    private void initViews() {
        mListView = (ListView) findViewById(R.id.list_view);
        mHeadView = (TextView) findViewById(R.id.tv_head);
        mChannelAdapter = new ChannelAdapter(null);
        mBrowserBtn = (Button) findViewById(R.id.btn_browser);
        mWapBtn = (Button) findViewById(R.id.btn_wap);
        mSdkBtn = (Button) findViewById(R.id.btn_sdk);
        mBrowserBtn.setOnClickListener(this);
        mWapBtn.setOnClickListener(this);
        mSdkBtn.setOnClickListener(this);
        mNextBtn = (Button) findViewById(R.id.btn_next);
        mNextBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int i = ++mChecked;
                int size = mListView.getCount();
                if (i == size) {
                    i = 0;
                    mChecked = 0;
                }
                mListView.setItemChecked(i, true);
                mListView.smoothScrollToPosition(i);
                confirmStatus(i);
            }
        });
        mListView.setAdapter(mChannelAdapter);
        mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                mChecked = position;
                confirmStatus(mChecked);
            }
        });
        refreshList();
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        toolbar.setTitle(mTitle);
        toolbar.setTitleTextColor(Color.YELLOW);
        spinner = (Spinner) findViewById(R.id.spinner);
        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                TextView textView = (TextView) view;
                if (null != textView) {
                    String text = textView.getText().toString();
                    if (!TextUtils.isEmpty(text)) {
                        if (getString(R.string.all).equals(text)) {
                            mHeadView.setText(getString(R.string.all) + ":" + mListAll.size());
                            mChannelAdapter.setList(mListAll);
                        } else if (getString(R.string.browser).equals(text)) {
                            mHeadView.setText(getString(R.string.browser) + ":" + mListBrowser.size());
                            mChannelAdapter.setList(mListBrowser);
                        } else if (getString(R.string.sdk).equals(text)) {
                            mHeadView.setText(getString(R.string.sdk) + ":" + mListSDK.size());
                            mChannelAdapter.setList(mListSDK);
                        }
                        refreshList();
                    }
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });
    }

    @Override
    public void onPayDataResult() {

    }

    @Override
    public void onPayException(final int exceptionType, final String exceptionContent) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (null != exceptionContent) {
                    showToast(exceptionContent);
                } else {
                    PayExceptionType type = PayExceptionType.values()[exceptionType];
                    dismiss();
                    String str;
                    switch (type) {
                        case DATA_EXCEPTION: {
                            str = getString(R.string.data_exception);
                            break;
                        }
                        case ENCRYPT_EXCEPTION: {
                            str = getString(R.string.encrypt_exception);
                            break;
                        }
                        case GET_PAY_METHOD_FAILED: {
                            str = getString(R.string.get_pay_method_failed);
                            break;
                        }
                        case DECRYPT_EXCEPTION: {
                            str = getString(R.string.decrypt_exception);
                            break;
                        }
                        case RETURN_ERROR_DATA: {
                            str = getString(R.string.return_error_data);
                            break;
                        }
                        case PAY_SYSTEM_ID_EMPTY: {
                            str = getString(R.string.pay_system_id_empty);
                            break;
                        }
                        case SERVER_CONNECTION_EXCEPTION: {
                            str = getString(R.string.server_connection_exception);
                            break;
                        }
                        default: {
                            str = "";
                            break;
                        }
                    }
                    showToast(str);
                }
            }
        });

    }

    @Override
    public void onPayProgressDialog() {
        dismiss();
    }

    @Override
    public void onShowChannelList() {

    }


    private void dismiss() {
        if (null != mProgressDialog && mProgressDialog.isShowing()) {
            PayLogUtil.log("dismiss");
            mProgressDialog.dismiss();
        }
    }

    private void showToast(String str) {
        mToast.setText(str);
        mToast.show();
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        int type;
        switch (id) {
            case R.id.btn_browser:
                type = 0;
                mBeginTime = System.currentTimeMillis();
                mProgressDialog = ProgressDialog.show(ChannelActivity.this, "",
                        getString(R.string.pay_info), false, true, null);
                mProgressDialog.setCanceledOnTouchOutside(false);
                mPayUtil.getPayParam(mChecked, type);
                break;
            case R.id.btn_wap:
                type = 1;
                mBeginTime = System.currentTimeMillis();
                mProgressDialog = ProgressDialog.show(ChannelActivity.this, "",
                        getString(R.string.pay_info), false, true, null);
                mProgressDialog.setCanceledOnTouchOutside(false);
                mPayUtil.getPayParam(mChecked, type);
                break;
            case R.id.btn_sdk:
                index++;
                TimerControlInfo mTimerControlInfo = new TimerControlInfo();
                tblPassageTimeStatistics mPassageTimeStatistics = new tblPassageTimeStatistics();
                mPassageTimeStatistics.setPlatform(mTitle.replace(mPayInfo.getPayTypeName(), "").trim());
                mPassageTimeStatistics.setPayType(mPayInfo.getPayTypeName());
                mPassageTimeStatistics.setPassageName(mChannelAdapter.getList().get(mChecked).getChannelName());
                mTimerControlInfo.setIndex(index);
                mTimerControlInfos.add(index, mTimerControlInfo);
                mPassageTimeStatisticses.add(index, mPassageTimeStatistics);
                getToken();//token passage single pair

                /*mBeginTime = System.currentTimeMillis();
                mProgressDialog = ProgressDialog.show(ChannelActivity.this, "", getString(R.string.pay_info), false, true, null);
                mProgressDialog.setCanceledOnTouchOutside(false);
                mPayUtil.getPayParam(mChecked, type);*/
                break;
        }
    }

    private void setSDKStatus(boolean status) {
        mWapBtn.setEnabled(!status);
        mBrowserBtn.setEnabled(!status);
        mSdkBtn.setEnabled(status);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        mPayUtil.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    private void confirmStatus(int position) {
        if (null != mChannelAdapter) {
            List<PayChannelInfo> list = mChannelAdapter.getList();
            if (null != list) {
                if (list.get(position).getTypeCode().equals("SDK")) {
                    setSDKStatus(true);
                } else {
                    setSDKStatus(false);
                }
            }
        }
    }

    //change ListView data
    private void refreshList() {
        mPayUtil.setPayChannelInfo(mChannelAdapter.getList());
        if (mListView.getCount() > 0) {
            mListView.setItemChecked(0, true);
            mChecked = 0;
            confirmStatus(mChecked);
        }
    }

    private TokenParam getTokenParam() {
        Date date = new Date();
        String p1_usercode = mUserCode; //user define
        String CompKey = mComKey;//user define
        DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        String p2_order = dateFormat.format(date);
        String p3_money = mPrice;
        String p4_returnurl = "http://shangjia.jtpay.com/Form/TestReturn"; //user define
        String p5_notifyurl = "http://shangjia.jtpay.com/Form/TestNotice"; //user define
        String p6_ordertime = dateFormat.format(date);
        String p7_sign = JFTMD5Utils.getMD5(p1_usercode + "&" + p2_order + "&"
                + p3_money + "&" + p4_returnurl + "&" + p5_notifyurl + "&"
                + p6_ordertime + CompKey).toUpperCase();
        return new TokenParam(p1_usercode, p2_order, p3_money, p4_returnurl,
                p5_notifyurl, p6_ordertime, "SDK", p7_sign);
    }

    private void getToken() {
        OkHttpClient client = new OkHttpClient.Builder().connectTimeout(
                PayConstant.TIME_OUT, TimeUnit.SECONDS).
                readTimeout(PayConstant.TIME_OUT, TimeUnit.SECONDS).build();
        Retrofit retrofit = new Retrofit.Builder().baseUrl(JftConstants.JUN_FU_TONG_URL).
                client(client).build();
        APIInterface apiInterface = retrofit.create(APIInterface.class);
        TokenParam tokenParam = getTokenParam();

        Map<String, String> map = new HashMap<>();
        map.put("p1_usercode", tokenParam.getUserCode());
        map.put("p2_order", tokenParam.getOrder());
        map.put("p3_money", tokenParam.getMoney());
        map.put("p4_returnurl", tokenParam.getReturnUrl());
        map.put("p5_notifyurl", tokenParam.getNotifyUrl());
        map.put("p6_ordertime", tokenParam.getOrderTime());
        map.put("p9_paymethod", tokenParam.getMethod());
        map.put("p7_sign", tokenParam.getSign());

        // TODO: 2017/3/22 0022 get token  start time
        mTimerControlInfos.get(index).setStartDate(new Date());
        retrofit2.Call<ResponseBody> resultCall =
                apiInterface.getToken(mPayInfo.getPaySystemId(), map);
        resultCall.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(retrofit2.Call<ResponseBody> call,
                                   Response<ResponseBody> response) {
                JftLogUtil.log("get Token onResponse!");
                if (response.isSuccessful()) {
                    try {
                        String result = response.body().string();
                        JftLogUtil.log("result = " + result);
                        JSONObject jsonObject = new JSONObject(result);
                        String flag = jsonObject.getString("flag");
                        if ("1".equals(flag)) {
                            String token = jsonObject.getString("token");
                            if (TextUtils.isEmpty(token)) {
                                JftLogUtil.log("Token is empty!");
                                return;
                            }
                            // TODO: 2017/3/22 0022 get token  end time
                            mTimerControlInfos.get(index).setEndDate(new Date());
                            double tokenTime = getCostTime(mTimerControlInfos.get(index).
                                    getStartDate(), mTimerControlInfos.get(index).getEndDate());
                            mPassageTimeStatisticses.get(index).setTokenTime(String.valueOf(tokenTime));
                            mTimerControlInfos.get(index).setToken(token);
                            mTimerControlInfos.get(index).DateInfoClear();

                            mPayInfo.setToken(token);

                            int type = 2;
                            mBeginTime = System.currentTimeMillis();
                            mProgressDialog = ProgressDialog.show(ChannelActivity.this, "",
                                    getString(R.string.pay_info), false, true, null);
                            mProgressDialog.setCanceledOnTouchOutside(false);

                            mTimerControlInfos.get(index).setStartDate(new Date());
                            mPayUtil.getPayParam(mChecked, type);

                        } else if ("0".equals(flag)) {
                            String msg = jsonObject.getString("msg");
                            dismiss();
                            showToast(msg);
                        }
                    } catch (JSONException | IOException e) {
                        dismiss();
                        showToast(e.getMessage());
                        e.printStackTrace();
                    }
                }
            }

            @Override
            public void onFailure(retrofit2.Call<ResponseBody> call, Throwable t) {
                PayLogUtil.log("getToken onFailure");
            }
        });
    }

    // handler类接收数据
    Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            if (msg.what == PayConstant.TIMER_CONTROL) {
                for (int i = 0; i < mTimerControlInfos.size(); i++) {
                    if (mTimerControlInfos.get(i).isDown()) {
                        continue;
                    }
                    int timerCounts = mTimerControlInfos.get(i).getTimerCounts();
                    JftLogUtil.log("while cycle counts " + timerCounts);
                    if (timerCounts <= 1) {
                        mTimerControlInfos.get(i).setDown(true);
                    } else {
                        mTimerControlInfos.get(i).setTimerCounts(timerCounts - 1);
                    }
                }
            }
        }
    };

    // 线程类
    class ThreadShow implements Runnable {
        @Override
        public void run() {
            // TODO Auto-generated method stub
            while (TimerControl) {
                try {
                    Thread.sleep(5000);
                    Message msg = new Message();
                    msg.what = PayConstant.TIMER_CONTROL;
                    handler.sendMessage(msg);
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }


    private double getCostTime(Date startDate, Date endDate) {
        if (null != startDate && null != endDate) {
            double tomerValue = endDate.getTime() - startDate.getTime();
            return tomerValue / 1000;
        } else {
            return -1;
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (REQUEST_CODE == requestCode) {
            if (RESULT_CODE == resultCode) {
                int payStatus = data.getIntExtra(PAY_STATUS, ZERO_CODE);
                try {
                    mTimerControlInfos.get(mTimerControlInfos.get(index).getIndex()).setEndDate(new Date());
                    TimerControlInfo timerControlInfo = mTimerControlInfos.get(index);
                    double timeValue = getCostTime(timerControlInfo.getStartDate(),
                            timerControlInfo.getEndDate());
                    mPassageTimeStatisticses.get(index).setPayQueryTime(
                            String.valueOf(timeValue));
                    timeValue = Double.parseDouble(mPassageTimeStatisticses.get(index).getPullupTime())
                            + Double.parseDouble(mPassageTimeStatisticses.get(index).getPayQueryTime());
                    mPassageTimeStatisticses.get(index).setPayTotalTime(
                            String.valueOf(timeValue));
                } catch (Exception e) {
                    e.printStackTrace();
                    JftLogUtil.log("Time statistics error");
                    return;
                }
                if (payStatus == SUCCESS) {
                    showToast(getString(R.string.pay_success));
                    mTimerControlInfos.get(index).setDown(true);
                    mPassageTimeStatisticses.get(index).setPayStatus(getString(R.string.pay_success));
                } else {
                    showToast(getString(R.string.pay_failure));
                    mPassageTimeStatisticses.get(index).setPayStatus(getString(R.string.pay_failure));
                }
                insertTblPassageTimeStatistics(mPassageTimeStatisticses.get(index));
            }

        }
    }
}
